package com.fowo.api.service.handleWork;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.fowo.api.entity.InventoryList;
import com.fowo.api.entity.Product;
import com.fowo.api.inventory.entity.Inventory;
import com.fowo.api.inventory.mapper.InventoryMapper;
import com.fowo.api.inventory.model.*;
import com.fowo.api.inventory.model.form.InventoryExchangeFormVo;
import com.fowo.api.inventory.model.form.InventoryOutboundFormVo;
import com.fowo.api.inventory.model.form.InventoryStorageFormVo;
import com.fowo.api.inventory.service.InventoryBusinessService;
import com.fowo.api.mapper.InventoryListMapper;
import com.fowo.api.mapper.ProductMapper;
import com.fowo.api.model.inventory.list.InventoryListSubmitAction;
import com.fowo.api.model.inventory.list.InventoryListVo;
import com.fowo.api.model.inventory.list.subtable.InventoryListSubtableItemVo;
import com.fowo.api.model.inventory.list.subtable.InventoryListSubtableSearchParamPo;
import com.fowo.api.model.stock.in.StockInVo;
import com.fowo.api.model.stock.in.product.StockInProductItemVo;
import com.fowo.api.model.stock.out.StockOutVo;
import com.fowo.api.model.stock.out.product.StockOutProductItemVo;
import com.fowo.api.service.InventoryListSubtableService;
import com.fowo.api.service.StockInService;
import com.fowo.api.service.StockOutService;
import com.fowo.api.service.impl.InventoryListServiceImpl;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class InventoryListSubmit implements InventoryListSubmitAction {

    @Resource
    private InventoryListMapper inventoryListMapper;

    @Resource
    private InventoryListServiceImpl inventoryListService;

    @Resource
    private InventoryListSubtableService inventoryListSubtableService;
    @Resource
    private InventoryMapper inventoryMapper;
    @Resource
    private InventoryBusinessService inventoryBusinessService;
    @Resource
    private ProductMapper productMapper;
    @Resource
    private StockInService stockInService;
    @Resource
    private StockOutService stockOutService;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void run(Long id) throws Exception {
//        InventoryList inventoryList = inventoryListMapper.selectById(id);
        InventoryListVo inventoryList = inventoryListService.getVoById(id);
        Assert.notNull(inventoryList,"盘点单不存在");
        Assert.isTrue(inventoryList.getStatus().equals("2"),"当前单据状态不可进行此操作！");

//        InventoryListSubtableSearchParamPo generateInventoryDetailsSearchParamPo = new InventoryListSubtableSearchParamPo();
//        generateInventoryDetailsSearchParamPo.setParentInventoryList(id);
//        List<InventoryListSubtableItemVo> subList = inventoryListSubtableService.search(generateInventoryDetailsSearchParamPo);
        List<InventoryListSubtableItemVo> subList = inventoryList.getGenerateInventoryDetails();
        final long count = subList.stream().filter(s -> s.getFirmInventory() == null).count();
        if(count > 0){
            throw new Exception("没有盘点完，请继续盘点");
        }
        // 释放仓库库存
        InventoryExchangeFormVo warehouseFormVo = prepareUnLockWarehouse(inventoryList);
        inventoryBusinessService.exchange(warehouseFormVo);
        //释放仓位库存
        InventoryExchangeFormVo formVo = prepareUnLockInventory(inventoryList);
        inventoryBusinessService.exchange(formVo);

        final List<InventoryListSubtableItemVo> out = subList.stream().filter(s -> s.getIntensityDifference() < 0).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(out)){
            //盘亏出库
            InventoryOutboundFormVo outboundFormVo = prepareOutStockApply(inventoryList,out);
            inventoryBusinessService.outbound(outboundFormVo);

            //添加出库单
//            StockOutVo stockOutVo = buildStockOutVo(inventoryList,out);
//            stockOutService.create(stockOutVo);
        }

        final List<InventoryListSubtableItemVo> in = subList.stream().filter(s -> s.getIntensityDifference() > 0).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(in)){
            //盘盈入库
            InventoryStorageFormVo storageFormVo = prepareApplyInStorage(inventoryList,in);
            inventoryBusinessService.storage(storageFormVo);

            //添加入库单
//            StockInVo stockInVo = buildStockIn(inventoryList,in);
//            stockInService.create(stockInVo);
        }

        inventoryList.setStatus("3");
        inventoryListMapper.updateById(inventoryList);
    }


    /**
     * 准备用于 释放库存 的参数
     */
    protected InventoryExchangeFormVo prepareUnLockInventory(InventoryListVo vo) throws Exception {
        InventoryExchangeFormVo formVo = new InventoryExchangeFormVo();
        if (ReflectUtil.hasField(InventoryListVo.class, "remark")) {
            formVo.setRemark(Convert.toStr(ReflectUtil.getFieldValue(vo, "remark")));
        }
        formVo.setFrom(TargetTypeEnum.Normal);
        formVo.setTo(TargetTypeEnum.Normal);
        formVo.setFormNum(vo.getInventoryNumber());
        formVo.setFormOperator(vo.getLastUpdateUser().toString());
        formVo.setDocumentType("盘点释放库存");
        if(ObjectUtils.isEmpty(vo.getWarehouseStock())){
            throw new Exception("出仓库 为空");
        }
        formVo.setFromStockId(vo.getWarehouseStock());
        if(ObjectUtils.isEmpty(vo.getWarehouseStock())){
            throw new Exception("入仓库 为空");
        }
        formVo.setToStockId(vo.getWarehouseStock());
        formVo.setModel(PatternEnum.FIFO);
        for(InventoryListSubtableItemVo inventoryListSubtable : vo.getGenerateInventoryDetails()) {
//            if(inventoryListSubtable.getFirmInventory() == null){
//                throw new Exception(inventoryListSubtable.getTradeNameName()+"没有盘点");
//            }
            SimpleInventoryItem inventoryItem = new SimpleInventoryItem();
            inventoryItem.setId(inventoryListSubtable.getTradeName());
            InventoryExchangeVo exchangeItem = new InventoryExchangeVo();
            exchangeItem.setItem(inventoryItem);
            exchangeItem.setQty(String.valueOf(inventoryListSubtable.getInventory()).equals("null")?BigDecimal.valueOf(0):BigDecimal.valueOf(inventoryListSubtable.getInventory()));
            exchangeItem.setShopId(String.valueOf(inventoryListSubtable.getShop()).equals("null")? null:String.valueOf(inventoryListSubtable.getShop()));
            exchangeItem.setFnSku( String.valueOf(inventoryListSubtable.getFnsku()).equals("null")? null:String.valueOf(inventoryListSubtable.getFnsku()));
            Map<Long,Integer> binIds=new HashMap<>();
            binIds.put(inventoryListSubtable.getShippingSpace(),Integer.parseInt(String.valueOf(inventoryListSubtable.getInventory()).equals("null")? "0":String.valueOf(inventoryListSubtable.getInventory())));
            exchangeItem.setFromBinIds(binIds);
            Map<Long,Integer> toBinIds=new HashMap<>();
            toBinIds.put(inventoryListSubtable.getShippingSpace(),Integer.parseInt(String.valueOf(inventoryListSubtable.getInventory()).equals("null")? "0":String.valueOf(inventoryListSubtable.getInventory())));
            exchangeItem.setToBinIds(toBinIds);
            exchangeItem.setFromBinIdsType(TargetTypeEnum.Lock);
            exchangeItem.setToBinIdsType(TargetTypeEnum.Normal);
            exchangeItem.setCustomId(vo.getId());
            exchangeItem.setCustomBdId(inventoryListSubtable.getId());
            formVo.add(exchangeItem);
        }
        return formVo;
    }

    /**
     * 准备用于 释放库存_仓库 的参数
     */
    protected InventoryExchangeFormVo prepareUnLockWarehouse(InventoryListVo vo)
            throws Exception {
        InventoryExchangeFormVo formVo = new InventoryExchangeFormVo();
        if (ReflectUtil.hasField(InventoryListVo.class, "remark")) {
            formVo.setRemark(Convert.toStr(ReflectUtil.getFieldValue(vo, "remark")));
        }
        formVo.setFrom(TargetTypeEnum.Lock);
        formVo.setTo(TargetTypeEnum.Normal);
        formVo.setFormNum(vo.getInventoryNumber());
        formVo.setDocumentType("盘点释放库存");
        if (ObjectUtils.isEmpty(vo.getLastUpdateUser())) {
            throw new Exception("关联制单人为空");
        }
        formVo.setFormOperator(vo.getLastUpdateUser().toString());
        if (ObjectUtils.isEmpty(vo.getWarehouseStock())) {
            throw new Exception("出仓库 为空");
        }
        formVo.setFromStockId(vo.getWarehouseStock());
        if (ObjectUtils.isEmpty(vo.getWarehouseStock())) {
            throw new Exception("入仓库 为空");
        }
        formVo.setToStockId(vo.getWarehouseStock());
        formVo.setModel(PatternEnum.FIFO);
        for (InventoryListSubtableItemVo inventoryListSubtable : vo.getGenerateInventoryDetails()) {
            SimpleInventoryItem inventoryItem = new SimpleInventoryItem();
            inventoryItem.setId(inventoryListSubtable.getTradeName());
            InventoryExchangeVo exchangeItem = new InventoryExchangeVo();
            exchangeItem.setItem(inventoryItem);
            exchangeItem.setQty(
                    String.valueOf(inventoryListSubtable.getInventory()).equals("null")
                            ? BigDecimal.valueOf(0)
                            : BigDecimal.valueOf(inventoryListSubtable.getInventory())
            );
            exchangeItem.setShopId(
                    String.valueOf(inventoryListSubtable.getShop()).equals("null")
                            ? null
                            : String.valueOf(inventoryListSubtable.getShop())
            );
            exchangeItem.setFnSku(
                    String.valueOf(inventoryListSubtable.getFnsku()).equals("null")
                            ? null
                            : String.valueOf(inventoryListSubtable.getFnsku())
            );
            exchangeItem.setCustomId(vo.getId());
            exchangeItem.setCustomBdId(inventoryListSubtable.getId());
            formVo.add(exchangeItem);
        }
        return formVo;
    }



    /**
     * 准备用于 盘亏出库 的参数
     */
    protected InventoryOutboundFormVo prepareOutStockApply(InventoryList inventoryList,List<InventoryListSubtableItemVo> out){

        InventoryOutboundFormVo formVo = new InventoryOutboundFormVo();
        formVo.setSupportNegative(false);
        formVo.setFrom(TargetTypeEnum.Normal);
        formVo.setFormNum(inventoryList.getInventoryNumber());
        formVo.setFormOperator(inventoryList.getCreateUser().toString());
        formVo.setStockId(inventoryList.getWarehouseStock());
        formVo.setModel(PatternEnum.FIFO);
        formVo.setDocumentType("盘亏出库");
        for (InventoryListSubtableItemVo subtableItemVo : out) {
            SimpleInventoryItem inventoryItem = new SimpleInventoryItem();
            inventoryItem.setId(subtableItemVo.getTradeName());
            InventoryOutboundVo outboundItem = new InventoryOutboundVo();
            outboundItem.setItem(inventoryItem);
            outboundItem.setQty(BigDecimal.valueOf(subtableItemVo.getIntensityDifference()).abs());
            outboundItem.setShopId(
                    String.valueOf(subtableItemVo.getShop()).equals("null")
                            ? null
                            : String.valueOf(subtableItemVo.getShop())
            );
            outboundItem.setFnSku(
                    String.valueOf(subtableItemVo.getFnsku()).equals("null")
                            ? null
                            : String.valueOf(subtableItemVo.getFnsku())
            );
            Map<Long,Integer> binIds=new HashMap<>();
            binIds.put(subtableItemVo.getShippingSpace(),Integer.parseInt(String.valueOf(subtableItemVo.getIntensityDifference()).equals("null")? "0":String.valueOf(Math.abs(subtableItemVo.getIntensityDifference()))));
            outboundItem.setBinIds(binIds);
            outboundItem.setFromBinIdsType(TargetTypeEnum.Normal);
            outboundItem.setCustomId(inventoryList.getId());
            outboundItem.setCustomBdId(subtableItemVo.getId());
            formVo.add(outboundItem);
        }
        return formVo;
    }

    /**
     * 准备用于 盘盈入库 的参数
     */
    protected InventoryStorageFormVo prepareApplyInStorage(InventoryList inventoryList,List<InventoryListSubtableItemVo> in){

        InventoryStorageFormVo formVo = new InventoryStorageFormVo();
        formVo.setSupportNegative(false);
        formVo.setTo(TargetTypeEnum.Normal);
        formVo.setFormNum(inventoryList.getInventoryNumber());
        formVo.setFormOperator(inventoryList.getCreateUser().toString());
        formVo.setStockId(inventoryList.getWarehouseStock());
        formVo.setDocumentType("盘盈入库");
        for (InventoryListSubtableItemVo subtableItemVo : in) {
            SimpleInventoryItem inventoryItem = new SimpleInventoryItem();
            inventoryItem.setId(subtableItemVo.getTradeName());
            InventoryStorageVo storageItem = new InventoryStorageVo();
            storageItem.setItem(inventoryItem);
            storageItem.setQty(BigDecimal.valueOf(subtableItemVo.getIntensityDifference()));

            storageItem.setShopId(String.valueOf(subtableItemVo.getShop()).equals("null")? null:String.valueOf(subtableItemVo.getShop()));
            storageItem.setFnSku( String.valueOf(subtableItemVo.getFnsku()).equals("null")? null:String.valueOf(subtableItemVo.getFnsku()));
            Map<Long,Integer> binIds=new HashMap<>();
            binIds.put(subtableItemVo.getShippingSpace(),Integer.parseInt(String.valueOf(subtableItemVo.getIntensityDifference()).equals("null")? "0":String.valueOf(Math.abs(subtableItemVo.getIntensityDifference()))));
            storageItem.setBinIds(binIds);
            storageItem.setFromBinIdsType(TargetTypeEnum.Normal);
            storageItem.setCustomId(inventoryList.getId());
            storageItem.setCustomBdId(subtableItemVo.getId());

            Product product = productMapper.selectById(subtableItemVo.getTradeName());
            storageItem.setAmount(
                    product.getProcurementCost() == null ?
                    new BigDecimal(0)
                    : product.getProcurementCost().multiply(BigDecimal.valueOf(subtableItemVo.getIntensityDifference()))
            );
            formVo.add(storageItem);
        }
        return formVo;
    }

    /**
     * 构建入库单数据
     * @param inventoryList
     * @param in
     * @return
     */
    public StockInVo buildStockIn(InventoryList inventoryList,List<InventoryListSubtableItemVo> in){
        StockInVo stockInVo = new StockInVo();
        stockInVo.setWarehouse(inventoryList.getWarehouseStock());
        stockInVo.setReceiptType("RK001");
        stockInVo.setRemarks("盘点入库");
        stockInVo.setCostAllocationType("1");
        stockInVo.setWarehousingDate(new Date());
        List<StockInProductItemVo> productList = new ArrayList<>();
        for(InventoryListSubtableItemVo item : in){
            Product product = productMapper.selectById(item.getTradeName());
            StockInProductItemVo productItemVo = new StockInProductItemVo();
            productItemVo.setImg(item.getImg());
            productItemVo.setProductId(item.getTradeName());
            productItemVo.setSku(item.getSku());
            productItemVo.setQuantity(item.getIntensityDifference());
            productItemVo.setGoodProduct(item.getIntensityDifference());
            productItemVo.setDefectiveProduct(0);
            productItemVo.setPositions(item.getShippingSpace());
            BigDecimal procurementCost = product.getProcurementCost() == null ? new BigDecimal(0.00) : product.getProcurementCost();
            productItemVo.setUnitPrice(procurementCost);
            productItemVo.setUnitReceiptCost(procurementCost);
            productItemVo.setSubtotal(BigDecimal.valueOf(item.getIntensityDifference()).multiply(procurementCost));
            productItemVo.setShopId(item.getShop());
            productList.add(productItemVo);
        }
        stockInVo.setProductList(productList);
        return stockInVo;
    }

    /**
     * 构建出库单数据
     * @param inventoryList
     * @param out
     * @return
     */
    public StockOutVo buildStockOutVo(InventoryList inventoryList,List<InventoryListSubtableItemVo> out){
        StockOutVo stockOutVo = new StockOutVo();
        stockOutVo.setWarehouse(inventoryList.getWarehouseStock());
        stockOutVo.setType("CK002");
        stockOutVo.setOutTime(new Date());
        stockOutVo.setRemark("盘点出库");
        List<StockOutProductItemVo> stockOutProducts = new ArrayList<>();
        for(InventoryListSubtableItemVo item : out){
            Product product = productMapper.selectById(item.getTradeName());
            StockOutProductItemVo productItemVo = new StockOutProductItemVo();
            productItemVo.setProductId(item.getTradeName());
            productItemVo.setSku(item.getSku());
            productItemVo.setSid(item.getShop());
            productItemVo.setShopName(item.getShopShopName());
            productItemVo.setFnsku(item.getFnsku());
            productItemVo.setProductGoodNum(Math.abs(item.getIntensityDifference()));
            productItemVo.setQuantity(Math.abs(item.getIntensityDifference()));
            BigDecimal procurementCost = product.getProcurementCost() == null ? new BigDecimal(0.00) : product.getProcurementCost();
            productItemVo.setPrice(procurementCost);
            productItemVo.setSubtotal(BigDecimal.valueOf(Math.abs(item.getIntensityDifference())).multiply(procurementCost));

            stockOutProducts.add(productItemVo);
        }
        stockOutVo.setStockOutProducts(stockOutProducts);
        return stockOutVo;
    }

}
